﻿using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace Working.Domínio
{
  public enum Sexo { Masculino, Feminino };
  public enum EstadoCivil { Solteiro, Casado, Viúvo, Separado };

  [Serializable]
  public class Pessoa: Entidade
  {
    #region Contrutores ----------------------------------------------------------

    public Pessoa(string nome, DateTime dataDeNascimento)
    {
      this.Nome = nome;
      this.DataDeNascimento = dataDeNascimento;
    }

    public Pessoa(SerializationInfo info, StreamingContext context)
      : base(info, context)
    {
      this.BeginLoad();
      try
      {
        this.nome = info.GetString("Nome");
        this.dataDeNascimento = info.GetDateTime("DataDeNascimento");
        this.sexo = (Sexo)info.GetValue("Sexo", typeof(Sexo));
        this.endereçoResidêncial = (Endereço)info.GetValue("EndereçoResidêncial", typeof(Endereço));
        this.nomeDaMãe = info.GetString("NomeMãe");
        this.nomeDoPai = info.GetString("NomePai");
        this.naturalidade = (Cidade)info.GetValue("Naturalidade", typeof(Cidade));
        this.nacionalidade = (País)info.GetValue("Nacionalidade", typeof(País));
        this.carteiraDeIdentidade = (CarteiraDeIdentidade)info.GetValue("CarteiraDeIdentidade", typeof(CarteiraDeIdentidade));
        this.cpf = info.GetString("Cpf");
        this.estadoCivil = (EstadoCivil)info.GetValue("EstadoCivil", typeof(EstadoCivil));
      }
      finally
      {
        this.EndLoad();
      }
    }


    #endregion

    #region Propriedades ---------------------------------------------------------

    public virtual string Nome
    {
      get { return nome; }
      set
      {
        if(string.IsNullOrEmpty(value))
          throw new WorkingException("Nome não pode ser branco ou nulo.");

        SetProperty("Nome", ref this.nome, value);
      }
    }
    private string nome = string.Empty;

    public DateTime DataDeNascimento
    {
      get { return dataDeNascimento; }
      set { SetProperty("DataDeNascimento", ref this.dataDeNascimento, value); }
    }
    private DateTime dataDeNascimento = DateTime.MinValue;

    public Sexo Sexo
    {
      get { return sexo; }
      set { SetProperty("Sexo", ref this.sexo, value); }
    }
    private Sexo sexo = Sexo.Masculino;

    public Endereço EndereçoResidêncial
    {
      get { return endereçoResidêncial; }
      set { SetProperty("EndereçoResidêncial", ref this.endereçoResidêncial, value); }
    }
    private Endereço endereçoResidêncial;

    public string NomeDaMãe
    {
      get { return nomeDaMãe; }
      set { SetProperty("NomeDaMãe", ref this.nomeDaMãe, value); }
    }
    private string nomeDaMãe = string.Empty;

    public string NomeDoPai
    {
      get { return nomeDoPai; }
      set { SetProperty("NomeDoPai", ref this.nomeDoPai, value); }
    }
    private string nomeDoPai = string.Empty;

    public Cidade Naturalidade
    {
      get { return naturalidade; }
      set { SetProperty("Naturalidade", ref this.naturalidade, value); }
    }
    private Cidade naturalidade = null;

    public País Nacionalidade
    {
      get { return nacionalidade; }
      set { SetProperty("Nacionalidade", ref this.nacionalidade, value); }
    }
    private País nacionalidade;

    public CarteiraDeIdentidade CarteiraDeIdentidade
    {
      get { return carteiraDeIdentidade; }
    }
    private CarteiraDeIdentidade carteiraDeIdentidade;

    public virtual string Cpf
    {
      get { return cpf; }
      set 
      {
        //TODO: Fazer validação do CNPJ
        //CpfUtils.Validar(value)

        SetProperty("Cpf", ref this.cpf, value); 
      }
    }
    private string cpf;

    public EstadoCivil EstadoCivil
    {
      get { return estadoCivil; }
      set { SetProperty("EstadoCivil", ref this.estadoCivil, value); }
    }
    private EstadoCivil estadoCivil = EstadoCivil.Solteiro;

    public TimeSpan Idade
    {
      get { return DateTime.Today.Subtract(this.dataDeNascimento); }
    }

    #endregion

    #region Métodos --------------------------------------------------------------

    public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
    {
      base.GetObjectData(info, context);
      info.AddValue("Nome", this.Nome);
      info.AddValue("DataDeNascimento", this.DataDeNascimento);
      info.AddValue("Sexo", this.Sexo, typeof(Sexo));
      info.AddValue("EndereçoResidêncial", this.EndereçoResidêncial, typeof(Endereço));
      info.AddValue("NomeMãe", this.NomeDaMãe);
      info.AddValue("NomePai", this.NomeDoPai);
      info.AddValue("Naturalidade", this.Naturalidade, typeof(Cidade));
      info.AddValue("Nacionalidade", this.Nacionalidade, typeof(País));
      info.AddValue("CarteiraDeIdentidade", this.CarteiraDeIdentidade, typeof(CarteiraDeIdentidade));
      info.AddValue("EstadoCivil", this.EstadoCivil, typeof(EstadoCivil));

      if(this.Cpf == null)
        info.AddValue("Cpf", string.Empty);
      else
        info.AddValue("Cpf", this.Cpf.ToString());

    }

    public void AtribuirIdentidade(string registroGeral)
    {
      this.AtribuirIdentidade(registroGeral, DateTime.MinValue);
    }

    public void AtribuirIdentidade(string registroGeral, DateTime dataDeExpedição)
    {
      this.AtribuirIdentidade(registroGeral, dataDeExpedição, string.Empty, string.Empty);
    }

    public void AtribuirIdentidade(string registroGeral, DateTime dataDeExpedição,
        string orgãoEmissor, string unidadeFederativa)
    {
      CarteiraDeIdentidade novaCarteira = new CarteiraDeIdentidade(this, registroGeral);
      SetProperty("CarteiraDeIdentidade", ref this.carteiraDeIdentidade, novaCarteira);
      this.carteiraDeIdentidade.DataDeExpedição = dataDeExpedição;
      this.carteiraDeIdentidade.OrgãoEmissor = orgãoEmissor;
      this.carteiraDeIdentidade.UnidadeFederativa = unidadeFederativa;
    }

    #endregion
  }
}
